package no.sachmuld.methodcombination.api.reflection;

import no.sachmuld.methodcombination.api.BehaviourChain;
import no.sachmuld.methodcombination.api.Direction;
import no.sachmuld.methodcombination.api.reflection.component.*;

import java.lang.reflect.Method;

/**
 *
 */
public class Standard<R> extends DelegatingMethodCombination<Object, R> {

    @Override
    public Standard<R> build(final Class behaviourClass, final Method targetMethod) {

        final Direction direction = Direction.BOTTOM_UP;

        final AroundMethodCombination<Object, R>   around = new AroundMethodCombination<>(targetMethod.getName(), direction);
        final BeforeMethodCombination              before = new BeforeMethodCombination();
        final PrimaryMethodCombination<Object, R>  primary = new PrimaryMethodCombination<>(direction);
        final AfterMethodCombination               after = new AfterMethodCombination();

        buildChildren(behaviourClass, targetMethod, around, before, primary, after);

        executedBy(
                around.inner(
                        new AbstractMethodCombination<Object, R>() {

                            @Override
                            public R execute(Object targetObject, BehaviourChain<?> behaviourChain, Object... parameters) {

                                before.execute(targetObject, behaviourChain, parameters);

                                R result = primary.execute(targetObject, behaviourChain, parameters);

                                after.execute(targetObject, behaviourChain, parameters);

                                return result;
                            }
                        }));

        return this;

    }

}
